package controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.helpers.DefaultValidationEventHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.SAXException;

import model.MP3FileList;

public class XMLCache {

	/*****************************
	 * MEMBER
	 *****************************/
	private static Schema schema = null;
	
	/*****************************
	 * METHODS
	 * @throws JAXBException 
	 * @throws SAXException 
	 *****************************/
	
	public static void generateSchema() throws IOException, JAXBException, SAXException {
		final File baseDir = new File(".");
		class MySchemaOutputResolver extends SchemaOutputResolver {
		    public javax.xml.transform.Result createOutput( String namespaceUri, String suggestedFileName ) throws IOException {
		        return new StreamResult(new File(baseDir,"schema.xsd"));
		    }
		}
		JAXBContext context = JAXBContext.newInstance(model.MP3FileList.class);
		context.generateSchema(new MySchemaOutputResolver());
		
		SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
		schema = sf.newSchema(new File("schema.xsd"));
	}
	
	public static boolean hasToBeCached(String directory) {
		boolean alreadyCached = false;
		
		File Dir = new File(directory);
		File[] children = Dir.listFiles();
		File cacheFile = null;
		for(int i = 0; i < children.length; i++) {
			
			if(children[i].toString().endsWith("cache.xml")){

				alreadyCached = true;
				cacheFile = new File(children[i].toString());
			}
		}
		
		
		if(alreadyCached) {
			if(Dir.lastModified() > cacheFile.lastModified()) {
				cacheFile = null;
				return true;	//something changed in the directory
			}
			else {
				cacheFile = null;
				return false;	//cache is up to date
			}
		} 
		else {
			cacheFile = null;
			return true;	//not cached yet
		}
		
	
	}
	
	public static void createCache(String directory, MP3FileList list) {
		
		JAXBContext jc = null;
		try {
			jc = JAXBContext.newInstance(model.MP3FileList.class);
		} catch (JAXBException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		//create new cache.xml
		File cacheFile = new File(directory + "/cache.xml");
		
		System.out.println("exists: " + cacheFile.exists());
		if(cacheFile.exists()) {
			System.out.println("try do delete");
			cacheFile.setWritable(true);
			System.out.println(cacheFile.delete());
		}
		try {
			cacheFile = Files.createFile(Paths.get(directory + "/cache.xml")).toFile();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		//write data into cache.xml
		try(FileOutputStream fileOutputStream = new FileOutputStream(cacheFile)) {
			
			Marshaller m = jc.createMarshaller();
			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			m.setSchema(schema);
			m.marshal(list, fileOutputStream);
			fileOutputStream.close();
		}
		catch(IOException e) {
			e.printStackTrace();
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	public static MP3FileList readCache(String directory) {
		
		JAXBContext jc = null;
			
		try {
			
			jc = JAXBContext.newInstance(model.MP3FileList.class);
			Unmarshaller um = jc.createUnmarshaller();
			um.setSchema(schema);
			um.setEventHandler(new DefaultValidationEventHandler() {public boolean handleEvent(javax.xml.bind.ValidationEvent event) {return false;}});
			MP3FileList mp3list = (MP3FileList) um.unmarshal(new File(directory + "/cache.xml"));
			System.out.println("cache gelesen");
			return mp3list;
		}
		catch(Exception e) {
			System.out.println("validation error");
			return null;
		}
		finally {
			jc = null;
		}

	}
	
	public static void deleteCache(String directory) {
		File cacheFile = new File(directory+"/cache.xml");
		System.out.println("deleteCachemethod " + cacheFile.exists());
		if(cacheFile.exists()) {
			cacheFile.delete();
		}
	}
}
